#include <iostream>
#include <string>
#include <mysql/mysql.h>
#include <thread>
#include <chrono>

int main(int argc, char** argv)
{
    MYSQL mysql;
    mysql_library_init(0, nullptr, nullptr);
    mysql_init(&mysql);

    std::string host = "127.0.0.1";
    //std::string host = "192.168.0.203";
    std::string user = "mysql_test";
    std::string pass = "123456";
    std::string db   = "mysql";

    // 设定超时3s
    // MYSQL_OPT_CONNECT_TIMEOUT:链接超时时间
   //  MYSQL_OPT_OPTIONAL_RESULTSET_METADATA 获取表结构  mysql_options 参数 bool 打开/关闭
    int to =  3;
    
    int ret = mysql_options(&mysql, MYSQL_OPT_CONNECT_TIMEOUT, &to);
    if (ret != 0)
    {
        std::cout << "mysql options  fialed!" << mysql_error(&mysql) << std::endl;
    }
    
    //  默认阻塞
    if (nullptr== mysql_real_connect(&mysql, host.c_str(), user.c_str(), pass.c_str(), db.c_str(), 3306, nullptr, 0))
    {
        std::cout << "mysql connect  fialed!" << mysql_error(&mysql) << std::endl;
    }

    // 1. 执行sql语句
    // mysql_real_query:  不需要分号结束，必须获取结果集并清理不然报错
    // mysql_query:       sql语句中有\0 就结束 不能有二进制数据 不需要分号结束

    // 读user 表 
    std::string sql = "SELECT * FROM user";
    ret = mysql_real_query(&mysql, sql.c_str(), sql.length());
    // mysql real query failed! Commands out of sync; you can't run this command now
    // 必须获取结果集并清理不然报错
    // ret = mysql_query(&mysql, sql.c_str());

    if (0 != ret)
    {
        std::cout << "mysql real query failed! " << mysql_error(&mysql) << std::endl;
    }
    else
    {
        std::cout << "mysql real query success! " << mysql_error(&mysql) << std::endl;
    }

    // 2 获取结果集
    MYSQL_RES* result = mysql_use_result(&mysql);

   // 保存结果集 到缓存
   // MYSQL_RES* result = mysql_store_result(&mysql);   
    if (nullptr == result)
    {
        std::cout << "mysql_use_result failed! " << mysql_error(&mysql) << std::endl;
    }


    // 3 表结构获取
    // 两种方式
    /* 方式 1
    MYSQL_FIELD * mysql_fetch_field(MYSQL_RES *result)
    
    */
    
    /* 方式 2
    unsigned int mysql_num_fields(MYSQL_RES *res): 获取表字段数量
    MYSQL_FIELD *mysql_fetch_field_direct(MYSQL_RES *res, unsigned int fieldnr): 
    
    */

    // 方式1
    // MYSQL_FIELD* field;
    // while (nullptr != (field = mysql_fetch_field(result)))
    // {
    //     std::cout << field->name << std::endl;
    // }

    // std::cout << std::endl;

    // 方式 2 
    // 字段数量
    auto num = mysql_num_fields(result);

    for(unsigned int i = 0; i < num; ++i)
    {
        MYSQL_FIELD* field = mysql_fetch_field_direct(result, i);
        std::cout << field->name << "  ";
    }
    std::cout << "\n=================================================================================" << std::endl;
    MYSQL_ROW row;
    while(nullptr != (row = mysql_fetch_row(result)))
    {
        // 表中各个数据的长度
        unsigned long* row_len = mysql_fetch_lengths(result);
        for (unsigned int i = 0; i < num; ++i)
        {
            if (nullptr == row[i])
            {
                std::cout << " <null> [" << row_len[i] <<"]";
            }
            else
            {
                std::cout << row[i] << " [" << row_len[i] <<"] ";
            }
        }
        std::cout << "\n================================================================================="<< std::endl;
    }
    

    mysql_free_result(result);
    mysql_close(&mysql); 
    mysql_library_end();


    return 0;
} 